package com.qingniao.hb.web.servlet;

import com.alibaba.druid.util.StringUtils;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * @author xlzhang
 * @date 2023/4/17 10:34
 * 这里进行共性配置，这个servlet会作为当前项目中所有servlet的父类，因此这个类不需要加注解进行注册
 */
public class BaseServlet extends HttpServlet {

    /**
     * 建一个全局的模板引擎属性
     */
    private TemplateEngine templateEngine;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        // 构建一个基于web上下文的模板视图解析器
        ServletContextTemplateResolver templateResolver
                = new ServletContextTemplateResolver(config.getServletContext());
        // 自动当前模板要解析的视图类型 为 HTML
        templateResolver.setTemplateMode(TemplateMode.HTML);
        // 设置视图的前缀和后缀
        // 模板会将逻辑视图 home 转换为物理视图："/home.html"
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        // 设置缓存的持续时长
        // templateResolver.setCacheTTLMs(Long.valueOf(3600000L));
        // 开发时关闭缓存，上线时开启缓存
        templateResolver.setCacheable(false);
        // ⑥设置服务器端编码方式
        templateResolver.setCharacterEncoding("utf-8");
        // 创建模板引擎，绑定模板解析
        templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 统一处理post请求的编码
        request.setCharacterEncoding("utf-8");
        // 获取资源路径
        final String uri = request.getRequestURI();
        System.out.println("uri = " + uri);

        // 处理和获取要调用的方法名称
        String methodName = null;
        if (uri.endsWith(".html")) {
            methodName = uri.substring(uri.lastIndexOf("/") + 1, uri.indexOf(".html"));
            methodName = methodName + "Page";
        } else{
            methodName = uri.substring(uri.lastIndexOf("/") + 1);
        }
        System.out.println("methodName = " + methodName);  // ""   null

        // 判断当前的请求是否有具体的方法命名
        if(StringUtils.isEmpty(methodName)){
            // 默认跳转到登录页
            //response.sendRedirect("/login.html");
            process("login",request,response);
            return;
        }
        // 执行子类对应名称的方法,通过反射的方式直接执行
        System.out.println("当前对象：" + this);
        try {
            // 根据当前调用方法的对象，获取对应的类对象，再根据类对象及方法名称 获取相应的方法对象
            Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            // 执行方法
            method.invoke(this,request,response);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 自定义封装一个模板视图的响应方法
     * 在所有的子类servlet中可以调用返回视图
     */
    @SuppressWarnings("all")
    protected void process(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.设置响应体内容类型和字符集
        resp.setContentType("text/html;charset=UTF-8");
        // 2.创建WebContext对象
        WebContext webContext = new WebContext(req, resp, req.getServletContext());
        // 3.处理模板数据
        templateEngine.process(templateName, webContext, resp.getWriter());
    }
}
